/*
* @Author: dyiwen
* @Date:   2020-09-17 17:21:34
* @Last Modified by:   dyiwen
* @Last Modified time: 2020-09-21 20:16:39
 */
package main

import (
	"errors"
	"fmt"
	"gitee.com/dyiwen/nacos-golang"
	"github.com/modood/table"
	"github.com/urfave/cli"
	"os"
	"src/request"
	"strconv"
	"strings"
)

func checkerr(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func check_namespace(c *cli.Context) {
	if c.String("n") == "" {
		fmt.Println("-n cannot be empty\n")
		os.Exit(1)
	} else if _, ok := conf.Namespace[c.String("n")]; !ok {
		fmt.Printf("请使用get ns查看所有命名空间\n")
		os.Exit(1)
	} else {
		namespace = c.String("n")
	}
}

func check_group(c *cli.Context) {
	if c.String("g") != "DEFAULT_GROUP" {
		group = c.String("g")
	}
	if c.String("G") != "DEFAULT_GROUP" {
		group = c.String("G")
		group = strings.ToUpper(group)
	}
}

func check_file(c *cli.Context, flag string) {
	if c.String(flag) == "" {
		fmt.Println("-f 指定需要导入的配置文件")
		os.Exit(1)
	} else if !IsFile(c.String(flag)) {
		fmt.Println("指定的路径不是文件或文件不存在")
		os.Exit(1)
	}
}

func check_file_exist(c *cli.Context, flag string) {
	if IsFile(c.String(flag)) {
		fmt.Printf("指定的文件已存在: %s\n", c.String(flag))
		os.Exit(1)
	}
}

func check_args(c *cli.Context) {
	if c.Args().First() == "" {
		fmt.Println("error: Required resource not specified.")
		os.Exit(1)
	}
}

func checkHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	fmt.Printf("Cureent User: %s \n", conf.User)
	fmt.Printf("Cureent Namespace: public \n")
	fmt.Printf("Cureent WebSite: %s \n", conf.Url)
	return nil
}

func getHandler(c *cli.Context) error {
	fmt.Printf("language=%v in namespace %v \n", c.Args().First(), c.String("n"))
	return nil
}

func getNamespaceHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	url_ := fmt.Sprintf("http://%s%s/v1/console/namespaces", conf.Url, conf.Prefix)
	r, err := request.Get(url_, request.Param{})
	checkerr(err)
	err = json_to_struct(r.Body)
	checkerr(err)
	var array []NsTable
	for k, v := range nsbox.Data {
		capacity := fmt.Sprintf("%2.2f %%", v.ConfigCount/v.Quota*100)
		conf.Namespace[v.Namespace] = struct{}{}
		temp := NsTable{k, v.Namespace, v.NamespaceShowName, v.ConfigCount, capacity}
		array = append(array, temp)
	}
	err = write_to_config(conf)
	checkerr(err)
	t := table.Table(array)
	fmt.Println(t)
	home := os.Getenv("HOMES")
	fmt.Println(home)
	return err
}

func searchHandler(c *cli.Context) error {
	return nil
}

func getDataidHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_namespace(c)
	a := nacos.InitConfig(conf.Url, conf.Prefix, namespace, conf.User, conf.Password, logdir, cachedir, conf.Port)
	b, err := a.CreateConfigClient()
	checkerr(err)
	if c.Args().First() != "" {
		dataid = c.Args().First()
	}
	check_group(c)
	if c.Int("i") != 0 {
		page = c.Int("i")
	}
	if c.Int("s") != 0 {
		pagesize = c.Int("s")
	}
	result, err := b.SearchConfig(mode, dataid, group, page, pagesize)
	checkerr(err)
	var array []Table
	var total string
	var page_num string
	var pageavailable string
	for k, v := range result.PageItems {
		total, page_num, pageavailable = "", "", ""
		if k == 0 {
			total = strconv.Itoa(result.TotalCount)
			page_num = strconv.Itoa(result.PageNumber)
			pageavailable = strconv.Itoa(result.PagesAvailable)
		}
		temp := Table{k, v.DataId, v.Group, total, page_num, pageavailable}
		array = append(array, temp)
	}
	pprintf(array)
	return nil
}

func describeHandler(c *cli.Context) error {
	fmt.Println("11111111111111")
	return nil
}

func describeDataidHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_namespace(c)
	check_args(c)
	check_group(c)
	a := nacos.InitConfig(conf.Url, conf.Prefix, namespace, conf.User, conf.Password, logdir, cachedir, conf.Port)
	b, err := a.CreateConfigClient()
	checkerr(err)
	dataid = c.Args().First()
	result, err := b.GetConfig(dataid, group)
	if err != nil {
		fmt.Println("config not found, -g 默认DEFAULT_GROUP")
	} else {
		fmt.Println(result)
	}
	return nil
}

func publishHandler(c *cli.Context) error {
	fmt.Printf("请使用 import 从文件导入")
	return nil
}

func publishDataidHandler(c *cli.Context) error {
	fmt.Printf("请使用 import 从文件导入")
	return nil
}

func deleteHandler(c *cli.Context) error {
	fmt.Printf("language=%v \n", c.Args().First())
	return nil
}

func deleteDataidHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_namespace(c)
	check_args(c)
	check_group(c)
	a := nacos.InitConfig(conf.Url, conf.Prefix, namespace, conf.User, conf.Password, logdir, cachedir, conf.Port)
	b, err := a.CreateConfigClient()
	checkerr(err)
	dataid = c.Args().First()
	result, err := b.DeleteConfig(dataid, group)
	if result {
		fmt.Printf("[%s] Delete Success! %s", group, dataid)
	} else {
		fmt.Println(err)
	}
	return nil
}

func importHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_file(c, "f")
	check_namespace(c)
	check_group(c)
	_, a := ParseIniConfig(c.String("f"))
	nacos_init := nacos.InitConfig(conf.Url, conf.Prefix, namespace, conf.User, conf.Password, logdir, cachedir, conf.Port)
	client, err := nacos_init.CreateConfigClient()
	checkerr(err)
	for _, v := range a {
		for key, value := range v {
			success, err := client.PublishConfig(key, group, MapMergeToString(value))
			checkerr(err)
			if success {
				fmt.Printf("[%s]发布配置成功：%s \n", group, key)
			}
		}
	}
	return err
}

//导出指定dataid到文件
func exportHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	check_namespace(c)
	check_args(c)
	check_file_exist(c, "o")
	check_group(c)
	a := nacos.InitConfig(conf.Url, conf.Prefix, namespace, conf.User, conf.Password, logdir, cachedir, conf.Port)
	b, err := a.CreateConfigClient()
	checkerr(err)
	result, err := b.GetConfig(c.Args().First(), group)
	checkerr(err)
	content := fmt.Sprintf("[%s]\n%s", c.Args().First(), result)
	err = CreatePath([]byte(content), c.String("o"))
	checkerr(err)
	fmt.Printf("[%s]导出配置成功：%s \n", group, c.Args().First())
	return nil
}

func loginHandler(c *cli.Context) error {
	check_args(c)
	if c.String("pf") != "" {
		prefix = c.String("pf")
	}
	if c.Uint64("p") != 0 {
		port = c.Uint64("p")
	}
	if c.String("n") != "" {
		namespace = c.String("n")
	} else {
		fmt.Println("-n cannot be empty")
		return errors.New("-n cannot be empty")
	}

	fmt.Printf("Username:")
	fmt.Scanln(&user)
	fmt.Printf("Password:")
	fmt.Scanln(&password)
	// fmt.Println(c.Args().First())
	url := c.Args().First()
	if strings.Contains(url, "http://") {
		url = strings.Replace(url, "http://", "", 1)
	} else if strings.Contains(url, "https://") {
		url = strings.Replace(url, "https://", "", 1)
	}
	err := login(url, prefix, namespace, user, password, logdir, cachedir, port)
	if err != nil {
		fmt.Println("Login Failed!")
		fmt.Println(err)
	} else {
		fmt.Printf("Login Succeeded! http://%s \n", url)
		conf = Config{
			Url:       url,
			User:      user,
			Password:  password,
			Port:      port,
			Prefix:    prefix,
			Namespace: map[string]struct{}{namespace: struct{}{}},
		}
		err = write_to_config(conf)
		if err != nil {
			fmt.Println(err)
		}
	}
	return nil
}

func logoutHandler(c *cli.Context) error {
	err := file_to_struct()
	checkerr(err)
	err = RemoveFile(path)
	checkerr(err)
	fmt.Println(conf.Url, "Logout Succeeded!\n")
	return nil
}
